package com.kinyx.framework.utils;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.util.XArrayList;

import org.junit.Assert;
import org.junit.Test;

public class KListUtils_Tester_distinct {

	class Bean {
		XArrayList<String> listMain;
		XArrayList<String> listAdd;
		Comparator<String> comparato;
		String result1;
		String result2;
		public Bean(final XArrayList<String> listMain, final XArrayList<String> listAdd, final Comparator<String> comparato, final String result) {
			super();
			this.listMain = listMain;
			this.listAdd = listAdd;
			this.comparato = comparato;
			this.result1 = result;
			this.result2 = result == null ? null : result.replaceAll("\"", "");
		}
	}

	final List<XArrayList<String>> cases = new XArrayList<XArrayList<String>>()//
			.xAdd(null)//
			.xAdd(new XArrayList<String>())//
			.xAdd(new XArrayList<String>().xAdd(null))//
			.xAdd(new XArrayList<String>().xAdd(""))//
			.xAdd(new XArrayList<String>().xAdd("foo"))//
			.xAdd(new XArrayList<String>().xAdd("bar"))//
			.xAdd(new XArrayList<String>().xAdd("foo").xAdd("bar"))//
	;

	@Test
	public void test() {
		Assert.assertNull(KListUtils.distinct(null, null, null));

		Assert.assertEquals("[]", KListUtils.distinct(Collections.emptyList(), null, null).toString());
		Assert.assertEquals("[]", KListUtils.distinct(null, Collections.emptyList(), null).toString());
		Assert.assertEquals("[]", KListUtils.distinct(Collections.emptyList(), Collections.emptyList(), null).toString());

		Comparator<String> comparato = null;
		final XArrayList<Bean> list1 = new XArrayList<Bean>()//
				.xAdd(new Bean(this.cases.get(0), this.cases.get(0), comparato, null))//
				.xAdd(new Bean(this.cases.get(0), this.cases.get(1), comparato, "[]"))//
				.xAdd(new Bean(this.cases.get(0), this.cases.get(2), comparato, "[null]"))//
				.xAdd(new Bean(this.cases.get(0), this.cases.get(3), comparato, "[\"\"]"))//
				.xAdd(new Bean(this.cases.get(0), this.cases.get(4), comparato, "[\"foo\"]"))//
				.xAdd(new Bean(this.cases.get(0), this.cases.get(5), comparato, "[\"bar\"]"))//
				.xAdd(new Bean(this.cases.get(0), this.cases.get(6), comparato, "[\"foo\", \"bar\"]"))//

				.xAdd(new Bean(this.cases.get(1), this.cases.get(0), comparato, "[]"))//
				.xAdd(new Bean(this.cases.get(1), this.cases.get(1), comparato, "[]"))//
				.xAdd(new Bean(this.cases.get(1), this.cases.get(2), comparato, "[null]"))//
				.xAdd(new Bean(this.cases.get(1), this.cases.get(3), comparato, "[\"\"]"))//
				.xAdd(new Bean(this.cases.get(1), this.cases.get(4), comparato, "[\"foo\"]"))//
				.xAdd(new Bean(this.cases.get(1), this.cases.get(5), comparato, "[\"bar\"]"))//
				.xAdd(new Bean(this.cases.get(1), this.cases.get(6), comparato, "[\"foo\", \"bar\"]"))//

				.xAdd(new Bean(this.cases.get(2), this.cases.get(0), comparato, "[null]"))//
				.xAdd(new Bean(this.cases.get(2), this.cases.get(1), comparato, "[null]"))//
				.xAdd(new Bean(this.cases.get(2), this.cases.get(2), comparato, "[null]"))//
				.xAdd(new Bean(this.cases.get(2), this.cases.get(3), comparato, "[null, \"\"]"))//
				.xAdd(new Bean(this.cases.get(2), this.cases.get(4), comparato, "[null, \"foo\"]"))//
				.xAdd(new Bean(this.cases.get(2), this.cases.get(5), comparato, "[null, \"bar\"]"))//
				.xAdd(new Bean(this.cases.get(2), this.cases.get(6), comparato, "[null, \"foo\", \"bar\"]"))//

				.xAdd(new Bean(this.cases.get(3), this.cases.get(0), comparato, "[\"\"]"))//
				.xAdd(new Bean(this.cases.get(3), this.cases.get(1), comparato, "[\"\"]"))//
				.xAdd(new Bean(this.cases.get(3), this.cases.get(2), comparato, "[\"\", null]"))//
				.xAdd(new Bean(this.cases.get(3), this.cases.get(3), comparato, "[\"\"]"))//
				.xAdd(new Bean(this.cases.get(3), this.cases.get(4), comparato, "[\"\", \"foo\"]"))//
				.xAdd(new Bean(this.cases.get(3), this.cases.get(5), comparato, "[\"\", \"bar\"]"))//
				.xAdd(new Bean(this.cases.get(3), this.cases.get(6), comparato, "[\"\", \"foo\", \"bar\"]"))//

				.xAdd(new Bean(this.cases.get(4), this.cases.get(0), comparato, "[\"foo\"]"))//
				.xAdd(new Bean(this.cases.get(4), this.cases.get(1), comparato, "[\"foo\"]"))//
				.xAdd(new Bean(this.cases.get(4), this.cases.get(2), comparato, "[\"foo\", null]"))//
				.xAdd(new Bean(this.cases.get(4), this.cases.get(3), comparato, "[\"foo\", \"\"]"))//
				.xAdd(new Bean(this.cases.get(4), this.cases.get(4), comparato, "[\"foo\"]"))//
				.xAdd(new Bean(this.cases.get(4), this.cases.get(5), comparato, "[\"foo\", \"bar\"]"))//
				.xAdd(new Bean(this.cases.get(4), this.cases.get(6), comparato, "[\"foo\", \"bar\"]"))//

				.xAdd(new Bean(this.cases.get(5), this.cases.get(0), comparato, "[\"bar\"]"))//
				.xAdd(new Bean(this.cases.get(5), this.cases.get(1), comparato, "[\"bar\"]"))//
				.xAdd(new Bean(this.cases.get(5), this.cases.get(2), comparato, "[\"bar\", null]"))//
				.xAdd(new Bean(this.cases.get(5), this.cases.get(3), comparato, "[\"bar\", \"\"]"))//
				.xAdd(new Bean(this.cases.get(5), this.cases.get(4), comparato, "[\"bar\", \"foo\"]"))//
				.xAdd(new Bean(this.cases.get(5), this.cases.get(5), comparato, "[\"bar\"]"))//
				.xAdd(new Bean(this.cases.get(5), this.cases.get(6), comparato, "[\"bar\", \"foo\"]"))//

				.xAdd(new Bean(this.cases.get(6), this.cases.get(0), comparato, "[\"foo\", \"bar\"]"))//
				.xAdd(new Bean(this.cases.get(6), this.cases.get(1), comparato, "[\"foo\", \"bar\"]"))//
				.xAdd(new Bean(this.cases.get(6), this.cases.get(2), comparato, "[\"foo\", \"bar\", null]"))//
				.xAdd(new Bean(this.cases.get(6), this.cases.get(3), comparato, "[\"foo\", \"bar\", \"\"]"))//
				.xAdd(new Bean(this.cases.get(6), this.cases.get(4), comparato, "[\"foo\", \"bar\"]"))//
				.xAdd(new Bean(this.cases.get(6), this.cases.get(5), comparato, "[\"foo\", \"bar\"]"))//
				.xAdd(new Bean(this.cases.get(6), this.cases.get(6), comparato, "[\"foo\", \"bar\"]"))//

		;
		list1.forEach(bean -> { Assert.assertEquals(bean.result1, KListUtils.toString(KListUtils.distinct(bean.listMain, bean.listAdd, bean.comparato), true)); });
		list1.forEach(bean -> { Assert.assertEquals(bean.result2, KListUtils.toString(KListUtils.distinct(bean.listMain, bean.listAdd, bean.comparato), false)); });

		comparato = (o1, o2) -> { return -1; };// 自定义比较方法，返回值!=0表示不去重。
		final XArrayList<Bean> list2 = new XArrayList<Bean>()//
				.xAdd(new Bean(this.cases.get(0), this.cases.get(0), comparato, null))//
				.xAdd(new Bean(this.cases.get(0), this.cases.get(1), comparato, "[]"))//
				.xAdd(new Bean(this.cases.get(0), this.cases.get(2), comparato, "[null]"))//
				.xAdd(new Bean(this.cases.get(0), this.cases.get(3), comparato, "[\"\"]"))//
				.xAdd(new Bean(this.cases.get(0), this.cases.get(4), comparato, "[\"foo\"]"))//
				.xAdd(new Bean(this.cases.get(0), this.cases.get(5), comparato, "[\"bar\"]"))//
				.xAdd(new Bean(this.cases.get(0), this.cases.get(6), comparato, "[\"foo\", \"bar\"]"))//

				.xAdd(new Bean(this.cases.get(1), this.cases.get(0), comparato, "[]"))//
				.xAdd(new Bean(this.cases.get(1), this.cases.get(1), comparato, "[]"))//
				.xAdd(new Bean(this.cases.get(1), this.cases.get(2), comparato, "[null]"))//
				.xAdd(new Bean(this.cases.get(1), this.cases.get(3), comparato, "[\"\"]"))//
				.xAdd(new Bean(this.cases.get(1), this.cases.get(4), comparato, "[\"foo\"]"))//
				.xAdd(new Bean(this.cases.get(1), this.cases.get(5), comparato, "[\"bar\"]"))//
				.xAdd(new Bean(this.cases.get(1), this.cases.get(6), comparato, "[\"foo\", \"bar\"]"))//

				.xAdd(new Bean(this.cases.get(2), this.cases.get(0), comparato, "[null]"))//
				.xAdd(new Bean(this.cases.get(2), this.cases.get(1), comparato, "[null]"))//
				.xAdd(new Bean(this.cases.get(2), this.cases.get(2), comparato, "[null, null]"))//
				.xAdd(new Bean(this.cases.get(2), this.cases.get(3), comparato, "[null, \"\"]"))//
				.xAdd(new Bean(this.cases.get(2), this.cases.get(4), comparato, "[null, \"foo\"]"))//
				.xAdd(new Bean(this.cases.get(2), this.cases.get(5), comparato, "[null, \"bar\"]"))//
				.xAdd(new Bean(this.cases.get(2), this.cases.get(6), comparato, "[null, \"foo\", \"bar\"]"))//

				.xAdd(new Bean(this.cases.get(3), this.cases.get(0), comparato, "[\"\"]"))//
				.xAdd(new Bean(this.cases.get(3), this.cases.get(1), comparato, "[\"\"]"))//
				.xAdd(new Bean(this.cases.get(3), this.cases.get(2), comparato, "[\"\", null]"))//
				.xAdd(new Bean(this.cases.get(3), this.cases.get(3), comparato, "[\"\", \"\"]"))//
				.xAdd(new Bean(this.cases.get(3), this.cases.get(4), comparato, "[\"\", \"foo\"]"))//
				.xAdd(new Bean(this.cases.get(3), this.cases.get(5), comparato, "[\"\", \"bar\"]"))//
				.xAdd(new Bean(this.cases.get(3), this.cases.get(6), comparato, "[\"\", \"foo\", \"bar\"]"))//

				.xAdd(new Bean(this.cases.get(4), this.cases.get(0), comparato, "[\"foo\"]"))//
				.xAdd(new Bean(this.cases.get(4), this.cases.get(1), comparato, "[\"foo\"]"))//
				.xAdd(new Bean(this.cases.get(4), this.cases.get(2), comparato, "[\"foo\", null]"))//
				.xAdd(new Bean(this.cases.get(4), this.cases.get(3), comparato, "[\"foo\", \"\"]"))//
				.xAdd(new Bean(this.cases.get(4), this.cases.get(4), comparato, "[\"foo\", \"foo\"]"))//
				.xAdd(new Bean(this.cases.get(4), this.cases.get(5), comparato, "[\"foo\", \"bar\"]"))//
				.xAdd(new Bean(this.cases.get(4), this.cases.get(6), comparato, "[\"foo\", \"foo\", \"bar\"]"))//

				.xAdd(new Bean(this.cases.get(5), this.cases.get(0), comparato, "[\"bar\"]"))//
				.xAdd(new Bean(this.cases.get(5), this.cases.get(1), comparato, "[\"bar\"]"))//
				.xAdd(new Bean(this.cases.get(5), this.cases.get(2), comparato, "[\"bar\", null]"))//
				.xAdd(new Bean(this.cases.get(5), this.cases.get(3), comparato, "[\"bar\", \"\"]"))//
				.xAdd(new Bean(this.cases.get(5), this.cases.get(4), comparato, "[\"bar\", \"foo\"]"))//
				.xAdd(new Bean(this.cases.get(5), this.cases.get(5), comparato, "[\"bar\", \"bar\"]"))//
				.xAdd(new Bean(this.cases.get(5), this.cases.get(6), comparato, "[\"bar\", \"foo\", \"bar\"]"))//

				.xAdd(new Bean(this.cases.get(6), this.cases.get(0), comparato, "[\"foo\", \"bar\"]"))//
				.xAdd(new Bean(this.cases.get(6), this.cases.get(1), comparato, "[\"foo\", \"bar\"]"))//
				.xAdd(new Bean(this.cases.get(6), this.cases.get(2), comparato, "[\"foo\", \"bar\", null]"))//
				.xAdd(new Bean(this.cases.get(6), this.cases.get(3), comparato, "[\"foo\", \"bar\", \"\"]"))//
				.xAdd(new Bean(this.cases.get(6), this.cases.get(4), comparato, "[\"foo\", \"bar\", \"foo\"]"))//
				.xAdd(new Bean(this.cases.get(6), this.cases.get(5), comparato, "[\"foo\", \"bar\", \"bar\"]"))//
				.xAdd(new Bean(this.cases.get(6), this.cases.get(6), comparato, "[\"foo\", \"bar\", \"foo\", \"bar\"]"))//

		;
		list2.forEach(bean -> { Assert.assertEquals(bean.result1, KListUtils.toString(KListUtils.distinct(bean.listMain, bean.listAdd, bean.comparato), true)); });
		list2.forEach(bean -> { Assert.assertEquals(bean.result2, KListUtils.toString(KListUtils.distinct(bean.listMain, bean.listAdd, bean.comparato), false)); });
	}

}
